package com.pakazaka.json;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import static java.lang.System.getProperty;
import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author Riseremi
 */
public class ParseJSON {

    /**
     * separates a multiple properties in a json file
     */
    public static final String PROPEERTY_SEPARATOR = "::";

    public static String removeSpacesExludingQuotes(String json) {
        boolean quote = false;
        char[] charArray = json.toCharArray();
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < charArray.length; i++) {
            if (charArray[i] == '"') {
                quote = !quote;
            }
            if (charArray[i] != ' ') {
                sb.append(charArray[i]);
            }
            if (quote && charArray[i] == ' ') {
                sb.append(charArray[i]);
            }
        }
        return sb.toString();
    }

    private static String getStringFromInputStream(InputStream is) throws IOException {
        StringBuilder sb = new StringBuilder();
        String line;
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        while ((line = br.readLine()) != null) {
            sb.append(line).append(getProperty("line.separator"));
        }
        return sb.toString();
    }

    public static String readWholeFile(String path) throws FileNotFoundException, IOException {
        InputStream is = ParseJSON.class.getClass().getResourceAsStream(path);

        StringBuilder sb = new StringBuilder();
        String line;
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        while ((line = br.readLine()) != null) {
            sb.append(line).append(getProperty("line.separator"));
        }
        return sb.toString();

    }

    public static String removeCommaInTheEnd(String string) {
        string = (string.lastIndexOf(',') == -1) ? string.substring(0, string.length() - 1) : string.substring(0, string.lastIndexOf(','));
        return string;
    }

    public static String[] splitByColon(String json) {
        return json.split(":");
    }

    public static String[] getStrings(String json) {
        String[] strings = clearArray(json.split("stop|\\n"));
        for (int i = 0; i < strings.length; i++) {
            strings[i] = removeCommaInTheEnd(strings[i]);
        }
        return strings;
    }

    public static String removeQuotes(String json) {
        return json.replaceAll("\"", "");
    }

    public static String removeBraces(String json) {
        return json.replaceAll("\\{", "").replaceAll("}", "");
    }

    public static String[] clearArray(String[] array) {
        ArrayList<String> newa = new ArrayList<>();
        for (String array1 : array) {
            if (!(array1.length() < 2) && !array1.startsWith("//")) {
                newa.add(array1);
            }
        }
        String[] res = new String[newa.size()];
        for (int i = 0; i < res.length; i++) {
            res[i] = newa.get(i);
        }
        return res;
    }

    public static String[] getObjects(String json) {
        json = removeSpacesExludingQuotes(json.trim());
        json = json.substring(1, json.length() - 2);
        String[] objs = json.split("},");
        for (int i = 0; i < objs.length; i++) {
            objs[i] = removeBraces(objs[i]);
        }
        return objs;
    }

    public static boolean isBordersCorrect(String json) {
        return json.startsWith("[") && json.substring(0, json.length() - 2).endsWith("]");
    }

    public static boolean isArrayValue(String str) {
        return str.contains(",");
    }

    /**
     * FINAL PARSE METHOD
     *
     * @param path
     * @return
     * @throws IOException
     */
    public static HashMap parseJSON(String path) throws IOException {
        String json = readWholeFile(path);
        if (isBordersCorrect(json)) {
            String[] objects = getObjects(json);
            HashMap<String, String> hm = new HashMap<>();

            for (String object : objects) {
                String[] strings = getStrings(object);
                strings = clearArray(strings);

                for (String string : strings) {
                    String[] byColon = splitByColon(string);
                    for (int m = 0; m < byColon.length; m++) {
                        byColon[m] = removeQuotes(byColon[m]);
                    }
                    for (int k = 0; k < byColon.length; k += 2) {
                        hm.put(byColon[k], byColon[k + 1]);
                    }
                }
            }
            return hm;
        } else {
            return null;
        }
    }

    /**
     *
     * @param path
     * @return
     * @throws IOException
     */
    public static ArrayList<HashMap<String, String>> parseJSONArray(String path) throws IOException {
        String json = readWholeFile(path);
        if (isBordersCorrect(json)) {
            String[] objects = getObjects(json);
            ArrayList<HashMap<String, String>> hmArray = new ArrayList<>();

            for (String object : objects) {
                HashMap<String, String> tempHm = new HashMap<>();
                String[] strings = getStrings(object);
                strings = clearArray(strings);
                for (String string : strings) {

                    //System.out.println(string);
                    String[] byColon = splitByColon(string);
                    for (int m = 0; m < byColon.length; m++) {
                        byColon[m] = removeQuotes(byColon[m]);

                        //array here
                        if (byColon[m].startsWith("[") && byColon[m].endsWith("]")) {
                            byColon[m] = byColon[m].replaceAll("\\[", "").replaceAll("]", "").replaceAll(",", PROPEERTY_SEPARATOR);
                        }
                    }
                    for (int k = 0; k < byColon.length - 1; k += 2) {
                        tempHm.put(byColon[k], byColon[k + 1]);
                    }
                }
                hmArray.add(tempHm);
            }
            return hmArray;
        } else {
            return null;
        }
    }
}
